﻿// =====================================================================
//
//  This file is part of the Microsoft Dynamics CRM SDK code samples.
//
//  Copyright (C) Microsoft Corporation.  All rights reserved.
//
//  This source code is intended only as a supplement to Microsoft
//  Development Tools and/or on-line documentation.  See these other
//  materials for detailed information regarding Microsoft code samples.
//
//  THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//
// =====================================================================

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace SL.IdentityModel.Claims
{
	/// <summary>
	/// This class contains a collection of Claim objects
	/// </summary>
	public class ClaimCollection : IList<Claim>, ICollection<Claim>, IEnumerable<Claim>, IEnumerable
	{
		private List<Claim> _claims;

		/// <summary>
		/// Creates an instance of a ClaimsCollection object
		/// </summary>
		public ClaimCollection()
		{
			_claims = new List<Claim>();
		}

		/// <summary>
		/// Allows indexing claims based on ClaimType name or Uri
		/// If there are more than one  matching claims, the first wll be returned.
		/// 
		/// </summary>
		/// <example>claimsCollection["Email"] can be used to retieve the Email claim type</example>
		/// <param name="key"></param>
		/// <returns></returns>
		public Claim this[string key]
		{
			get
			{
				string claimType = key;
				Claim claim = null;

				if (null == claimType)
				{
					claimType = key;
				}

				claim = (from c in _claims
						 where c.ClaimType == claimType
						 select c).FirstOrDefault<Claim>();

				return claim;
			}
		}

		#region ICollection

		public int Count
		{
			get { return this._claims.Count; }
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public void Clear()
		{
			_claims.Clear();
		}

		public void Add(Claim item)
		{
			if (null == item)
			{
				throw new ArgumentNullException("item");
			}
			_claims.Add(item);
		}

		public bool Contains(Claim item)
		{
			return _claims.Contains(item);
		}

		public void CopyTo(Claim[] array, int arrayIndex)
		{
			_claims.CopyTo(array, arrayIndex);
		}

		public bool Remove(Claim item)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}

			if (!_claims.Remove(item))
			{
				throw new InvalidOperationException("attempt was made to remove an item that was not in the collection");
			}

			return true;
		}
		#endregion

		#region IEnumerable<Claim>

		public IEnumerator<Claim> GetEnumerator()
		{
			return _claims.GetEnumerator();
		}

		#endregion

		#region IEnumerable

		IEnumerator IEnumerable.GetEnumerator()
		{
			return _claims.GetEnumerator();
		}

		#endregion

		#region IList

		public Claim this[int index]
		{
			get { return this._claims[index]; }
			set { this.Insert(index, value); }
		}

		public void AddRange(IEnumerable<Claim> collection)
		{
			if (null == collection)
			{
				throw new ArgumentNullException("collection");
			}

			foreach (Claim claim in collection)
			{
				this.Add(claim);
			}
		}

		public int IndexOf(Claim item)
		{
			return _claims.IndexOf(item);
		}

		public void Insert(int index, Claim item)
		{
			if ((index < 0) || (index >= _claims.Count))
			{
				throw new ArgumentOutOfRangeException("index");
			}

			if (item == null)
			{
				throw new ArgumentNullException("item");
			}

			_claims.Insert(index, item);
		}

		public void RemoveAt(int index)
		{
			if ((index < 0) || (index >= _claims.Count))
			{
				throw new ArgumentOutOfRangeException("index is out of supported rant");
			}

			Claim item = _claims[index];
			this.Remove(item);
		}
		#endregion
	}
}
